﻿/**	file.h
 *	----	Create Time Stamp	--2007-09-28 20:28:05--
 *------------------------------------------------------------------------------
 *	Mean	:
 *	Author	:Nick Shallery	(nicknide@gmail.com)
 *	Version	:1.0.29.43	(2009-09-10 22:03:41)
 *------------------------------------------------------------------------------
**/	/*YOU HAVE ALL LEFT WITH THIS CODE WHILE YOU KEEP COMMENT IN EVERY COPY.*/

#if			!defined(__LOLIX__LOLI__FILE__K_IN_G__)
#define		__LOLIX__LOLI__FILE__K_IN_G__
//==============================================================================
//--------------------------------------------------------------------------

#if			!defined(__LOLIX__LOLI_X_MACRO__K_IN_G__)
	#include	"../lolix_macro.h"
#endif	//	!defined(__LOLIX__LOLI_X_MACRO__K_IN_G__)
#if			!defined(__LOLIX__LOLIX_TYPE__K_IN_G__)
	#include	"../lolix_type.h"
#endif	//	!defined(__LOLIX__LOLIX_TYPE__K_IN_G__)
#if			!defined(__LOLIX__TOY__L_X_ASSERT_NICK__K_IN_G__)
	#include	"../toy/lx_assert.h"
#endif	//	!defined(__LOLIX__TOY__L_X_ASSERT_NICK__K_IN_G__)
#if			!defined(__LOLIX__TOY__REBIND_TYPE__K_IN_G__)
	#include	"../toy/rebind_type.hpp"
#endif	//	!defined(__LOLIX__TOY__REBIND_TYPE__K_IN_G__)


namespace lolix{namespace loli{
	namespace _help{
		class	LOLIX_NO_VTABLE	__T_file_volume_base;
		class	LOLIX_NO_VTABLE	__T_file_sys_base;
	}

class LOLIX_NO_VTABLE file;
class LOLIX_NO_VTABLE file_volume;
class LOLIX_NO_VTABLE file_volume_group;

__LOLIX_DEFINE_ID_INTERFACE(ftype_std_file, (0x6c629f00, 0xb44bf807, 0xc115c27a, 0x5190f2a4));	//	, L"file:"};
__LOLIX_DEFINE_ID_INTERFACE(ftype_std_pmem,	(0xf395caca, 0xb4d9efe3, 0xd24e8e19, 0x72c2795d));	//	, L"pmem:"};	//	PhyMem Memory File
__LOLIX_DEFINE_ID_INTERFACE(ftype_std_zipf,	(0x7047aa4c, 0x24f1d34d, 0xf1090069, 0x489133f9));	//	, L"zipf:"};	//	Zip File File
__LOLIX_DEFINE_ID_INTERFACE(ftype_std_http,	(0x95bb2ce3, 0xb443bc9b, 0x3ec06ce9, 0x5eaf24c4));	//	, L"http:"};
__LOLIX_DEFINE_ID_INTERFACE(ftype_std_munt,	(0x95bb2ce3, 0xb443bc9b, 0x3ec06ce9, 0x5eaf24c4));	//	, L"munt:"};	//	Mounted Root Path

class LOLIX_NO_VTABLE file_flow;
class LOLIX_NO_VTABLE file_stream;
class LOLIX_NO_VTABLE file_block;

enum FILE_BLOCK_MAPPING_TYPE;
enum FILE_OPEN_FLAG;
}}

enum	lolix::loli::FILE_OPEN_FLAG
{
#define	__LOLIX_TMP__DEFINE_FILE_OPEN_FLAG_ITEM(type, value, comment)	type = value ,
#include	"_file_open_flag.inl"
};

class LOLIX_NO_VTABLE lolix::loli::_help::__T_file_sys_base
	: public lolix::itf
{
public:
	struct open_flag;

	typedef	FILE_OPEN_FLAG	FILE_OPEN_FLAG;
	#define	__LOLIX_TMP__DEFINE_FILE_OPEN_FLAG_ITEM(type, value, comment)	static const FILE_OPEN_FLAG type = lolix::loli::type;
	#include	"_file_open_flag.inl"
};


__BEGIN_DISABLE_NO_NAME_STRUCT_WARNING();
struct	lolix::loli::_help::__T_file_sys_base::open_flag
{
	typedef	lx_u32	flag_type;
	LOLIX_INLINE_CALL	open_flag(void){}
	LOLIX_INLINE_CALL	explicit open_flag(flag_type v):flag(v){}

	typedef	FILE_OPEN_FLAG	FILE_OPEN_FLAG;
	#define	__LOLIX_TMP__DEFINE_FILE_OPEN_FLAG_ITEM(type, value, comment)	static const FILE_OPEN_FLAG type = lolix::loli::type;
	#include	"_file_open_flag.inl"

	enum
	{	create_new			= 1
	,	create_always		= 2
	,	open_existing		= 3
	,	open_always			= 4
	,	truncate_existing	= 5

	,	mask_operat			= FILE_OPEN_OPERAT_MASK
	,	mask_optimi			= FILE_OPEN_OPTIMI_MASK
	,	mask_open_type		= FILE_OPEN_TYPE_MASK
	,	mask_with			= FILE_OPEN_WITH_MASK
	,	mask_share			= FILE_OPEN_SHARE_MASK
	,	mask_attr			= FILE_OPEN_ATTR_MASK

	,	dis_operat			= FILE_OPEN_OPERAT_DISTANCE
	,	dis_optimi			= FILE_OPEN_OPTIMI_DISTANCE
	,	dis_type			= FILE_OPEN_TYPE_DISTANCE
	,	dis_with			= FILE_OPEN_WITH_DISTANCE
	,	dis_share			= FILE_OPEN_SHARE_DISTANCE
	,	dis_attr			= FILE_OPEN_ATTR_DISTANCE

	,	_ver				= FILE_OPEN_VER
	};

	union
	{
		flag_type		flag;
		struct
		{
			//	+0x00	bits
			flag_type	operat_read		: 1;
			flag_type	operat_write	: 1;
			flag_type	operat_execute	: 1;
			flag_type	_rsv_00			: 5;

			//	+0x08	bits
			flag_type	type_mask		: 3;
			flag_type	with_flow		: 1;	//	流 : 单向， 不可回退
			flag_type	with_block		: 1;
			flag_type	with_bidir		: 1;	//	双向:修饰流专用， 和 flow 标记组合为 stream
			flag_type	share_read		: 1;
			flag_type	share_write		: 1;

			//	+0x10
			flag_type	attr_temp		: 1;
			flag_type	make_path		: 1;
			flag_type	_rsv_04			: 6;

			//	+0x18
			flag_type	_rsv_05			: 3;
			flag_type	optimi_stream	: 1;
			flag_type	optimi_random	: 1;
			flag_type	optimi_mapping	: 1;
			flag_type	_rsv_01			: 2;

		};
		struct
		{
			flag_type	operat_flag		: 3;
			flag_type	_rsv_06			: 1;
			flag_type	optimi_flag		: 3;
			flag_type	_rsv_07			: 1;

			flag_type	_rsv_08			: 3;
			flag_type	with_flag		: 3;
			flag_type	share_flag		: 2;
		};
	};
};
STATIC_ASSERT(sizeof(lolix::loli::_help::__T_file_sys_base::open_flag) == sizeof(lolix::loli::_help::__T_file_sys_base::open_flag::flag_type));
__END_DISABLE_NO_NAME_STRUCT_WARNING();




class LOLIX_NO_VTABLE lolix::loli::_help::__T_file_volume_base
	: public __T_file_sys_base
{
protected:
	struct	_tagFileType
	{
		LOLIX_ITF_ID	id;
		const wchar_t*	name;
	};

	struct _tagMemPath
	{
		wchar_t			ftype_name[4];	//	= L"gmem" or L"lmem";
		//	if is std file, than use the max of file's size
		//	if is phy page object, it is means that any size, ex. others specified or the first time specified.
		size_type		mem_size;

		size_type		path_size;
		const wchar_t*	path;
	};

	//	do check if this class support the file fmt which named in_id;
	LOLIX_INTERFACE(chk_spt	, bool			, (LOLIX_ITF_ID const* in_id)const);

public:


	typedef _tagFileType		ftype;
	typedef	_tagMemPath			mem_path;
	//typedef	_tagFileUnreachable	unreach_able;
};



class LOLIX_NO_VTABLE lolix::loli::file
	: public _help::__T_file_sys_base
{
public:
	LOLIX_DECLARE_ITF(lolix::loli::file, lolix::itf, (0x519a0678, 0xd4cb65bc, 0x3c778819, 0xbc9962a3));

	LOLIX_INTERFACE(size		, lx_u64		, (void)const);
	LOLIX_INTERFACE(close		, LOLIX_RETNV	, (void));
	LOLIX_INTERFACE(opt_flag	, void			, (open_flag* const out)const);
	LOLIX_INTERFACE(get_name	, LOLIX_RETNV	, (LOLIX_ITF_ID* const out_id, wchar_t full_name[], size_type* const io_file_name_len)const);
	LOLIX_INTERFACE(remove		, LOLIX_RETNV	, (void));
	//	out_ptr can be null, but it maybe lost during some times.
	LOLIX_INTERFACE(reopen		, LOLIX_RETNV	, (file** out_ptr, size_type opt_flag, void* reserve));
};


class LOLIX_NO_VTABLE lolix::loli::file_volume
	: public lolix::loli::_help::__T_file_volume_base
{
public:
	//	lolix note : please don't query lolix stand interface by use this id, you must query it with &LOLIX_ITF_FROM_TYPE(lolix::loli::ftype_std_file) and so on
	LOLIX_DEFINE_FACTORY((0x6c753241, 0x4e8b4ebb, 0x9311ac74, 0x8705d584), (file_volume**, const wchar_t* root_path, size_type root_path_size));
	LOLIX_DECLARE_ITF(lolix::loli::file_volume, lolix::itf, (0x19233593, 0x3450045e, 0x8588b738, 0xa5b07ee8));
	enum ENUM_ITEM_TYPE
	{	ITEM_TYPE_FILE
	,	ITEM_TYPE_DIRECTOR
	,	_ITEM_TYPE_CNT
	,	_ITEM_TYPE_VER = 0
	};

	class LOLIX_NO_VTABLE enum_callback
	{
	public:
		LOLIX_INTERFACE(call_back	, bool	, (wchar_t const* file_name, size_type file_name_size, ENUM_ITEM_TYPE sub));
	};

	using _help::__T_file_volume_base::chk_spt;
	//	get this class all support fmt id.
	LOLIX_INTERFACE(get_ftype	, LOLIX_RETNV	, (LOLIX_ITF_ID* out_id)const);

	//===========================================================================
	//	open a file with special file name.
	//		the name'size must the true len of file name without last zero.
	//---------------------------------------------------------------------------
	//	file_ptr	[ o]	out put the file
	//	file_name	[i ]	the file name : without the file volume type descripte.
	//	name_size	[i ]	the file name's size; -1 are test name size by this object
	//	opt_flag	[i ]	open flag
	//---------------------------------------------------------------------------
	//TODO:返回值说明
	//===========================================================================
	LOLIX_INTERFACE(open		, LOLIX_RETNV	, (file** out_file_ptr, const wchar_t* in_file_name, size_type in_name_size, size_type in_opt_flag));
	LOLIX_INTERFACE(enum_items	, LOLIX_RETNV	, (wchar_t const* path_name, size_type path_size, enum_callback*)const);
	//LOLIX_INTERFACE(remove		, void			, (const wchar_t* file_name, size_type name_size));
};


class LOLIX_NO_VTABLE lolix::loli::file_volume_group
	: public lolix::loli::_help::__T_file_volume_base
{
public:
	LOLIX_DEFINE_FACTORY((0x639d1b1a, 0x4e934043, 0x954b07bc, 0x21f35187), (file_volume_group**/*, const LOLIX_ITF_ID* need_support, size_type need_support_buf_size*/));
	LOLIX_DECLARE_PROXY(lolix::loli::file_volume_group, (0x6803845d, 0x7fbe4ac8, 0x9e868811, 0xc5f13fb6));

	LOLIX_DECLARE_ITF(lolix::loli::file_volume_group, lolix::itf, (0x3a34d1f4, 0xa41c9308, 0xaef27979, 0x9faa1d2b));

	using _help::__T_file_volume_base::chk_spt;
	//	get this class all support fmt id.
	LOLIX_INTERFACE(enum_ftype	, LOLIX_RETNV	, (LOLIX_ITF_ID in_id[], size_type* const ft_size)const);

	LOLIX_INTERFACE(attach		, LOLIX_RETNV	, (lolix::loli::file_volume*, const LOLIX_ITF_ID* select_id_array));
	LOLIX_INTERFACE(detach		, LOLIX_RETNV	, (const lolix::loli::file_volume*, const LOLIX_ITF_ID* select_id_array));
	LOLIX_INTERFACE(reg_fmt		, LOLIX_RETNV	, (const wchar_t* name, size_type name_size, const LOLIX_ITF_ID* id));

	//	open a file with special file name. the name'size must the true len of file name without last zero.
	LOLIX_INTERFACE(open		, LOLIX_RETNV	, (lolix::loli::file**, LOLIX_ITF_ID const*const id, const wchar_t* file_name, size_type name_size, size_type file_opt_flag));
	LOLIX_INTERFACE(open		, LOLIX_RETNV	, (lolix::loli::file**, const wchar_t*, size_type name_size, size_type file_opt_flag));

	LOLIX_INTERFACE(query_proxy	, void			, (proxy_type** out_proxy)const);
};


class LOLIX_NO_VTABLE lolix::loli::file_flow
	: public lolix::loli::file
{
	class	_tagSyncCallBack{};
public:
	LOLIX_DECLARE_ITF(lolix::loli::file_flow, lolix::loli::file, (0xe46080d7, 0x7e6941f2, 0x940f30da, 0x77f08e11));
	enum	ENUM_SYNC_TYPE;
	typedef	_tagSyncCallBack	sync_call_back;

	//===========================================================================
	//	提取输入流的数据
	//---------------------------------------------------------------------------
	//	buf			[ o] : 输出缓冲区
	//	buf_size	[io] : i) 当前缓冲区的大小， o) 实际返回的字节数
	//	call_back	[  ] : 保留， 当前必须为 0
	//---------------------------------------------------------------------------
	//	不会更改当前缓冲区的指向， 并且不会影响当前流的内容
	//===========================================================================
	LOLIX_INTERFACE(touch	, LOLIX_RETNV	, (void* buf, size_type* buf_size, sync_call_back* call_back));

	//===========================================================================
	//	读取输入流的数据
	//---------------------------------------------------------------------------
	//	buf			[ o] : 输出缓冲区
	//	buf_size	[io] : i) 当前缓冲区的大小， o) 实际返回的字节数
	//	call_back	[  ] : 保留， 当前必须为 0
	//===========================================================================
	LOLIX_INTERFACE(read	, LOLIX_RETNV	, (void* buf, size_type* buf_size, sync_call_back* call_back));

	//===========================================================================
	//	写入到输入流
	//---------------------------------------------------------------------------
	//	buf			[ o] : 输入的数据
	//	buf_size	[io] : i) 当前缓冲区的大小， o) 实际写入的字节数
	//	call_back	[  ] : 保留， 当前必须为 0
	//===========================================================================
	LOLIX_INTERFACE(write	, LOLIX_RETNV	, (const void* buf	, size_type* buf_size, sync_call_back* call_back));
};


class LOLIX_NO_VTABLE lolix::loli::file_stream
	: public lolix::loli::file_flow
{
	class	_tagSyncCallBack;
public:
	LOLIX_DECLARE_ITF(lolix::loli::file_stream, lolix::loli::file_flow, (0x0e590074, 0x44cf8cbe, 0x62cd1cdb, 0xfd097714));
	//	new_offset: [in] need offset, [out] new offset >> distance of begining
	//	int : 0 -> from header, 1 -> from current, 2 -> from end
	LOLIX_INTERFACE(seek	, LOLIX_RETNV	, (lx_i64* new_offset, int));
};


class LOLIX_NO_VTABLE lolix::loli::file_stream::_tagSyncCallBack
	: public lolix::itf
{
public:
	LOLIX_DECLARE_ITF(lolix::loli::file_stream, lolix::itf, (0xad1b8ab9, 0xe44cbd54, 0xd6703d78, 0x5c95698f));
	LOLIX_INTERFACE(invoke,	void	, (ENUM_SYNC_TYPE, LOLIX_RETNV, void* buf, size_type buf_size));
};


class LOLIX_NO_VTABLE lolix::loli::file_block
	: public lolix::loli::file
{
public:
	LOLIX_DECLARE_ITF(lolix::loli::file_block*, lolix::loli::file, (0xac3e296a, 0xdddb4b8c, 0xa4280771, 0x184ada53));
	enum FILE_BLOCK_MAPPING_TYPE;

	//--------------------------------------------------------------------------
	//	>> 2007-04-12 22:06:26 >>------------------->> 2007-04-12 22:06:26 >>
	//FUNC>>$	:锁定所需要的内存并得到所需求的数据
	//FUNC>>@0	:[out]	返回的内存首地址, 如果请求失败则返回未定义
	//FUNC>>@1	:[in]	操作类型， 读取/写入/插入 等等操作
	//FUNC>>@2	:[in]	从多少个字节开始(如果是写方式, 则只需要 from <= size(), 则表示需要写入 len 长度的数据
	//FUNC>>@3	:[i/o]	in: 需求多少个字节的内存, out: 实际返回了多少个字节
	//FUNC>>#	:
	//			LOLIX_RETNV_OK				没有问题
	//			LOLIX_ERROR_INVALID_PARAM	参数错误
	//			LOLIX_ERROR_OUT_OF_RANGE	"from" 越界
	//--------------------------------------------------------------------------
	LOLIX_INTERFACE(mapping,	LOLIX_RETNV	,	(void** const ptr, size_type mapping_type, lx_u64 from, size_type* const len));

	//--------------------------------------------------------------------------
	//	>> 2007-04-12 22:21:16 >>------------------->> 2007-04-12 22:21:16 >>
	//FUNC>>$	:解除某个范围的锁定
	//FUNC>>@0	:[in]	需要解除的某个起始地址(必须是从 lock 返回的地址, 不能为0)
	//FUNC>>@1	:[in]	需要解除的内存长度, 0 表示全部
	//FUNC>>#	:
	//			LOLIX_RETNV_OK				没有问题
	//			LOLIX_ERROR_INVALID_MEMORY	传入的内存不合法
	//			LOLIX_WARNING_INVALID_STATE	opt_type 状态非法, 但是被纠正了
	//--------------------------------------------------------------------------
	LOLIX_INTERFACE(unmapping,	LOLIX_RETNV,	(void const* const ptr, size_type len/*, bool submit*/));

	class	auto_unmapping;
};


enum lolix::loli::file_block::FILE_BLOCK_MAPPING_TYPE
{
	MAPPING_TYPE_READ	= lolix::loli::file_volume::FILE_OPEN_OPERAT_READ
,	MAPPING_TYPE_WRITE	= lolix::loli::file_volume::FILE_OPEN_OPERAT_WRITE
,	MAPPING_TYPE_EXECUTE= lolix::loli::file_volume::FILE_OPEN_OPERAT_EXECUTE
,	MAPPING_TYPE_VER	= 0
};


class	lolix::loli::file_block::auto_unmapping
{
	size_type	_size;
	const void*	_ptr;
	file_block*	_fb;
public:
	LOLIX_INLINE_CALL	auto_unmapping(void):_ptr(0){}
	LOLIX_INLINE_CALL	auto_unmapping(file_block* fb, const void* ptr):_fb(fb), _ptr(ptr), _size(0){}
	LOLIX_INLINE_CALL	auto_unmapping(file_block* fb, const void* ptr, size_type mapping_size): _fb(fb), _ptr(ptr), _size(mapping_size){}
	LOLIX_INLINE_CALL	~auto_unmapping(void){__Clear();}
	LOLIX_INLINE_CALL	const void* release(void){ const void* ptr = _ptr; _ptr = 0; return ptr;}
	LOLIX_INLINE_CALL	void reset(void){__Clear();_ptr = 0;}
	LOLIX_INLINE_CALL	void reset(file_block* fb, const void* ptr, size_type size){__Clear(); _fb = fb; _ptr = ptr; _size = size;}
private:
	LOLIX_INLINE_CALL	void	__Clear(void){if (_ptr) _fb->unmapping(_ptr, _size);}
};



SYS_REGIST_TYPE(lolix::loli::_help::__T_file_sys_base::open_flag);
SYS_REGIST_TYPE(lolix::loli::_help::__T_file_volume_base::ftype);
SYS_REGIST_TYPE(lolix::loli::_help::__T_file_volume_base::mem_path);
SYS_REGIST_TYPE(lolix::loli::file);
SYS_REGIST_TYPE(lolix::loli::file_block);
SYS_REGIST_TYPE(lolix::loli::file_flow);
SYS_REGIST_TYPE(lolix::loli::file_flow::ENUM_SYNC_TYPE);
SYS_REGIST_TYPE(lolix::loli::file_flow::sync_call_back);
SYS_REGIST_TYPE(lolix::loli::file_stream);
SYS_REGIST_TYPE(lolix::loli::file_volume);
SYS_REGIST_TYPE(lolix::loli::file_volume::factory_type);
SYS_REGIST_TYPE(lolix::loli::file_volume_group);
SYS_REGIST_TYPE(lolix::loli::file_volume_group::factory_type);
SYS_REGIST_TYPE(lolix::loli::file_volume_group::proxy_type);


//--------------------------------------------------------------------------
//==============================================================================
#endif	//	!defined(__LOLIX__LOLI__FILE__K_IN_G__)
